package com.ywu.verify.standard.utils;

import com.ywu.boot.utils.RedisUtils;
import com.ywu.verify.spi.dto.TypeEnum;
import com.ywu.verify.spi.dto.VerifyParamDto;
import com.ywu.verify.standard.common.VerifyConstant;
import com.ywu.verify.standard.config.VerifyConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName VerifyUtils
 * @Description TODO
 * @Author GroundDemo
 * @Date 2023/11/11 20:07
 * @Version 1.0
 **/
public class VerifyUtils {

    private static String verifyLetters = "";

    /**
    * @Author GroundDemo
    * @Description 生成验证码 画出image图像
    * @Date 21:00 2023/11/11
    * @Param [types, len]
    * @return Map
    **/
    public static Map<String, Object> generateVerifyImage(VerifyParamDto dto){
        //创建一张图片
        BufferedImage verifyPic = new BufferedImage(120,40,BufferedImage.TYPE_3BYTE_BGR);
        //通过图片获取画笔
        Graphics2D g = verifyPic.createGraphics();
        // 获取随机验证码
        String verifyCode = generateVerifyCode(dto.getTypes(), dto.getLen());
        //将图片的底板由黑变白
        g.setColor(Color.white);
        g.fillRect(0, 0, dto.getWidth(), dto.getHeight());
        //将验证码画在图片之上
        g.setFont(new Font(dto.getFontName(),Font.BOLD, dto.getFontSize()));
        for (int i = 0; i < verifyCode.length(); i++) {
            //随机产生一个角度
            double theta = Math.random() * Math.PI / 6 * ((int)(Math.random()*2) == 0?1:-1);
            //产生偏转
            g.rotate(theta, 5 + i * dto.getFontSize() * 0.91, dto.getHeight() / 2.0);
            //每画一个字幕之前都随机给一个颜色
            g.setColor(new Color((int)(Math.random()*256), (int)(Math.random()*256), (int)(Math.random()*256)));
            g.drawString(verifyCode.charAt(i)+"", (int)(5 + i * dto.getFontSize() * 0.91) , (int)(dto.getHeight() * 0.65));
            //回正
            g.rotate(-theta, 5 + i * dto.getFontSize() * 0.91, dto.getHeight() / 2.0);
        }
        //加入干扰线
        for (int i = 0; i < dto.getInterfereSize(); i++) {
            //给随机颜色
            g.setColor(new Color((int)(Math.random() * 256), (int)(Math.random() * 256), (int)(Math.random() * 256)));
            //画线
            g.drawLine((int)(Math.random() * dto.getWidth()), (int)(Math.random() * dto.getHeight()),
                    (int)(Math.random() * dto.getWidth()), (int)(Math.random() * dto.getHeight()));
        }
        Map<String, Object> resMap = new HashMap<>();
        resMap.put(VerifyConstant.VERIFY_CODE_KEY, verifyCode);
        resMap.put(VerifyConstant.VERIFY_CODE_PIC_KEY, verifyPic);
        // 将verifyCode添加至redis缓存
        String uniqueKeyInfo = UUID.randomUUID().toString().replace("-", "");
        String redisKey = CacheNameUtils.getVerifyRedisCacheKey() + ":" + uniqueKeyInfo;
        RedisUtils.set(redisKey, verifyCode);
        RedisUtils.setExpire(redisKey, 20, TimeUnit.MINUTES);
        resMap.put(VerifyConstant.VERIFY_CODE_REDIS_KEY, uniqueKeyInfo);
        return resMap;
    }

    /**
    * @Author GroundDemo
    * @Description 获取验证码生成的基础字符串
    * @Date 20:11 2023/11/11
    * @Param type 待生成的基数类型
    * @return java.lang.String
    **/
    private static String getVerifyRandomLetter(List<TypeEnum> type) {
        StringBuilder res = new StringBuilder();
        // 避免重复添加类型，使用set集合进行过滤
        Set<TypeEnum> existTypeEnums = new HashSet<>();
        for (TypeEnum typeEnum : type) {
            if (existTypeEnums.contains(typeEnum)) {
                continue;
            }
            switch (typeEnum) {
                case WORD:
                    res.append(VerifyConstant.WORD_UP + VerifyConstant.WORD_LOW);
                    existTypeEnums.add(TypeEnum.WORD_LOW);
                    existTypeEnums.add(TypeEnum.WORD_UP);
                    break;
                case WORD_LOW:
                    res.append(VerifyConstant.WORD_LOW);
                    existTypeEnums.add(TypeEnum.WORD_LOW);
                    break;
                case WORD_UP:
                    res.append(VerifyConstant.WORD_UP);
                    existTypeEnums.add(TypeEnum.WORD_UP);
                    break;
                case SPECIAL_CHAR:
                    res.append(VerifyConstant.SPECIAL_CHAR);
                    existTypeEnums.add(TypeEnum.SPECIAL_CHAR);
                    break;
                case NUMBER:
                    res.append(VerifyConstant.NUMBER);
                    existTypeEnums.add(TypeEnum.NUMBER);
                    break;
                default:
                    res.append("");
            }
        }
        return res.toString();
    }

    /**
    * @Author GroundDemo
    * @Description 生成随机验证码
    * @Date 20:38 2023/11/11
    * @Param len 验证码长度
    * @return java.lang.String
    **/
    private static String generateVerifyCode(List<TypeEnum> type, int len) {
//        // 判断当前类中的verifyLetter是否为空 为空调用方法生成
//        if (StringUtils.isBlank(verifyLetters)) {
//            verifyLetters = getVerifyRandomLetter(type);
//        }
        // 支持动态配置的方式动态刷新值
        verifyLetters = getVerifyRandomLetter(type);
        StringBuilder resVerifyCode = new StringBuilder();
        // 每次获取随机下标的位置的char进行拼接
        for (int i = 0; i < len; i++) {
            char ch = verifyLetters.charAt((int) (Math.random() * verifyLetters.length()));
            resVerifyCode.append(ch);
        }
        return resVerifyCode.toString();
    }
}
